#![allow(warnings)]

use std::{sync::{Arc, RwLock, Mutex}, time::{SystemTime, UNIX_EPOCH}};

use crate::{classfile::{ClassFile, BootstrapMethodsAttribute, BootstrapMethod, EnclosingMethodAttribute}, rtda::{Slots, Object}};

use super::{access_flags::{ACC_PUBLIC, ACC_FINAL, ACC_SUPER, ACC_INTERFACE, ACC_ABSTRACT, ACC_SYNTHETIC, ACC_ANNOTATION, ACC_ENUM}, field::Field, method::Method, ClassLoader, ConstantPool, class_name_helper::{get_array_class_name, PRIMITIVE_TYPES}, Constant};

// 将要放进方法区内的类
#[derive(Default, Clone)]
pub struct Class {
    access_flags: u16, // 访问标识
    name: String, // 类名称
    super_class_name: String, // 父类名称
    interface_names: Vec<String>, // 接口名称
    constant_pool: Option<Arc<ConstantPool>>, // 运行时常量池 类文件中的常量池
    fields: Vec<Arc<Field>>, // 字段表
    methods: Vec<Arc<Method>>, // 方法表
    loader: Option<Arc<Mutex<ClassLoader>>>, // 类加载器
    super_class: Option<Arc<Class>>, // 父类指针
    interfaces: Vec<Arc<Class>>, // 接口指针
    instance_slot_count: usize, // 实例变量数，包括所有父类层级
    static_slot_count: usize, // 静态变量数
    static_vars: Arc<RwLock<Slots>>, // 存储static值, 未被final修饰的常量可修改，常量主要以读为主用RwLock实现。
    init_started: bool,
    init_lock: Option<Arc<Mutex<()>>>, // 初始化锁，仅允许获取到此锁的线程进行初始化。
    j_class: Option<*mut Object>, // java.lang.Class实例，类关联对象指针。
    source_file: String, // 生成这个Class文件的源码文件名称。
    this: Option<Arc<Class>>, // 存储自身引用
    original_class: Option<Arc<Class>>, // 仅匿名类为Some，用于创建匿名类所提供的原始类
    bootstrap_methods: Option<BootstrapMethodsAttribute>, // 存储classfile中的BootstrapMethods属性
    enclosing_method: Option<EnclosingMethodAttribute>, //  存储classfile中的EnclosingMethod属性
}
// j_class 类关联对象结构
// Object：T {
//     class 指向java.lang.Class类class
//     extra class类型 指向 T类class
//     ...
// }

impl Class {
    pub fn new_class(cf: ClassFile) -> Arc<Class> {
        let mut class = Arc::new(Class::default());
        // 231026 Class全部改为Arc，因constant_pool、fields、methods需要存class引用，先生成arc在通过unsafe赋值。除了此处还有初始化是需要用unsafe修改。
        unsafe {
            let class_ptr = Arc::as_ptr(&class) as *mut Class;
            let class_mut = { &mut *class_ptr };
            class_mut.access_flags = cf.access_flags();
            class_mut.name = cf.class_name();
            class_mut.super_class_name = cf.super_class_name();
            class_mut.interface_names = cf.interface_names();
            class_mut.bootstrap_methods = cf.bootstrap_methods(); // 创建常量池要用到放到常量池前面。
            class_mut.enclosing_method = cf.enclosing_method();
            class_mut.constant_pool = Some(ConstantPool::new_constant_pool(class.clone(), cf.constant_pool()));
            class_mut.fields = Field::new_fields(class.clone(), cf.filds());
            class_mut.methods = Method::new_methods(class.clone(), cf.methods());
            class_mut.source_file = Self::get_source_file_name(cf);
            class_mut.init_lock = Some(Arc::new(Mutex::new(())));
            class_mut.this = Some(class.clone());
        }
        class
    }

    pub fn new_shim() -> Class {
        let mut class = Class::default();
        class.name = "shim".to_string();
        class
    }

    // 新建匿名类
    pub fn new_anonymous_class(&self, cf: ClassFile, cp_patches: Option<&Vec<Option<*mut Object>>>) -> Arc<Class> {
        // 直接clone原始类
        let mut class = Arc::new(self.clone());
        // 231026 Class全部改为Arc，因constant_pool、fields、methods需要存class引用，先生成arc在通过unsafe赋值。除了此处还有初始化是需要用unsafe修改。
        unsafe {
            let loader = class.get_class_loader().unwrap();
            let class_ptr = Arc::as_ptr(&class) as *mut Class;
            let class_mut = { &mut *class_ptr };
            class_mut.access_flags = cf.access_flags();
            let now = SystemTime::now();
            let epoch = UNIX_EPOCH;
            let duration = now.duration_since(epoch).unwrap();
            let milliseconds = duration.as_nanos() as i64 % 10000000000;
            class_mut.name = cf.class_name() + &milliseconds.to_string();
            class_mut.super_class_name = cf.super_class_name();
            class_mut.interface_names = cf.interface_names();

            // 加载父类
            class_mut.super_class = Some(loader.lock().unwrap().load_class(cf.super_class_name()));
            // 加载接口
            let mut interfaces = vec![];
            for interface_name in cf.interface_names() {
                interfaces.push(loader.lock().unwrap().load_class(interface_name));
            }
            class_mut.interfaces = interfaces;

            class_mut.bootstrap_methods = cf.bootstrap_methods(); // 创建常量池要用到放到常量池前面。
            class_mut.enclosing_method = cf.enclosing_method();
            let cp = ConstantPool::new_constant_pool(class.clone(), cf.constant_pool());
            let ptr = Arc::as_ptr(&cp) as *mut ConstantPool;
            let rt_cp = { &mut *ptr };
            if let Some(cp_patches) = cp_patches{
                for i in 0..cp_patches.len() {
                    let cp_info = cp_patches[i];
                    if let Some(info) = cp_info {
                        rt_cp.consts[i] = Constant::new_by_obj(info, cp.clone());
                    }
                }
            }
            class_mut.constant_pool = Some(cp);
            class_mut.fields = Field::new_fields(class.clone(), cf.filds());
            class_mut.methods = Method::new_methods(class.clone(), cf.methods());
            class_mut.source_file = Self::get_source_file_name(cf);
            class_mut.init_lock = Some(Arc::new(Mutex::new(())));
            class_mut.this = Some(class.clone());

            // 存储原始类
            class_mut.original_class = self.this.clone();
        }
        class
    }

    fn get_source_file_name(cf: ClassFile) -> String {
        if let Some(sf_attr) = cf.source_file_attribute() {
            return sf_attr.file_name();
        }
        "Unknown".to_string()
    }

    pub fn new_object(class: Arc<Class>) -> Object {
        Object::new(class)
    }

    pub fn new_array_class(name: String, loader: Arc<Mutex<ClassLoader>>) -> Class {
        // 由于在class_loader中调用此方法， 已存在loader可变借用，将super_class于interfaces放到调用此方法的位置添加。
        Class {
            access_flags: ACC_PUBLIC, // TODO
            name,
            super_class_name: String::default(),
            interface_names: Vec::default(),
            constant_pool: None,
            fields: Vec::default(),
            methods: Vec::default(),
            loader: Some(loader.clone()),
            // super_class: Some(loader.borrow_mut().load_class("java/lang/Object".to_string(), loader.clone())),
            // interfaces: vec![loader.borrow_mut().load_class("java/lang/Cloneable".to_string(), loader.clone()), loader.borrow_mut().load_class("java/io/Serializable".to_string(), loader.clone())],
            super_class: None,
            interfaces: vec![],
            instance_slot_count: 0,
            static_slot_count: 0,
            static_vars: Arc::new(RwLock::new(Slots::default())),
            init_started: true, // 数组类已初始化。
            init_lock: None,
            j_class: None,
            source_file: String::default(),
            this: None,
            original_class: None,
            bootstrap_methods: None,
            enclosing_method: None,
        }
    }

    pub fn new_primitive_class(name: &str, loader: Arc<Mutex<ClassLoader>>) -> Arc<Class> {
        let mut class = Arc::new(Class::default());
        let class_mut = Arc::get_mut(&mut class).unwrap();
        class_mut.access_flags = ACC_PUBLIC;
        class_mut.name = name.to_string();
        class_mut.loader = Some(loader);
        class_mut.init_started = true;
        class
    }

    pub fn array_class(&self) -> Arc<Class> {
        let array_class_name = get_array_class_name(self.name.clone());
        let loader = self.loader.clone().unwrap();
        let class = loader.lock().unwrap().load_class(array_class_name);
        class
    }

    pub fn init_started(&self) -> bool {
        self.init_started
    }

    pub unsafe fn strat_init(&self) {
        // 此值仅修改一次，用unsafe实现。
        // {&mut *(self as *mut Class)}.init_started = true;
        let ptr = Arc::as_ptr(self.this.as_ref().unwrap()) as *mut Class;
        {&mut *ptr}.init_started = true;
    }

    pub fn get_init_lock(&self) -> Arc<Mutex<()>> {
        self.init_lock.clone().unwrap()
    }

    // pub fn set_constant_pool(&mut self, cp: Arc<ConstantPool>) {
    //     self.constant_pool = Some(cp);
    // }

    pub fn get_constant_pool(&self) -> Option<Arc<ConstantPool>> {
        self.constant_pool.clone()
    }

    pub fn set_static_vars(&mut self, slots: Slots){
        self.static_vars = Arc::new(RwLock::new(slots));
    }

    pub fn get_static_vars(&self) -> Arc<RwLock<Slots>>{
        self.static_vars.clone()
    }

    // TODO 231027 暂未测试是否会出现以下错误
    // 现报以下错误，先改为clone。直接循环会导致获取改值的class rc借用无法释放，循环中无法获取可变借用
    // temporary value dropped while borrowed
    // creates a temporary value which is freed while still in use
    pub fn get_fields(&self, public_only: bool) -> Vec<Arc<Field>> {
        if public_only {
            self.fields.clone().into_iter().filter(|field| field.is_public()).collect()
        } else {
            self.fields.clone()
        }
    }

    pub fn get_field(class: Option<Arc<Class>>, name: &str, descriptor: &str, is_static: bool) -> Option<Arc<Field>>{
        if let Some(c) = class {
            for field in &c.fields {
                if field.is_static() == is_static && field.get_name() == name && field.get_descriptor() == descriptor {
                    return Some(field.clone());
                }
            }
            let sc = c.super_class.clone();
            Self::get_field(sc, name, descriptor, is_static)
        } else {
            None
        }
    }

    pub fn get_field_by_name(class: Option<Arc<Class>>, name: &str) -> Option<Arc<Field>>{
        if let Some(c) = class {
            for field in &c.fields {
                if field.get_name() == name {
                    return Some(field.clone());
                }
            }
            let sc = c.super_class.clone();
            Self::get_field_by_name(sc, name)
        } else {
            None
        }
    }

    pub fn get_methods(&self, public_only: bool) -> Vec<Arc<Method>> {
        if public_only {
            self.methods.clone().into_iter().filter(|method| method.is_public()).collect()
        } else {
            self.methods.clone()
        }
    }

    pub fn set_class_loader(&mut self, cf: Arc<Mutex<ClassLoader>>) {
        self.loader = Some(cf)
    }

    pub fn get_class_loader(&self) -> Option<Arc<Mutex<ClassLoader>>> {
        self.loader.clone()
    }

    pub fn set_super_class(&mut self, super_class: Arc<Class>) {
        self.super_class = Some(super_class);
    }

    pub fn get_super_class(&self) -> Option<Arc<Class>> {
        self.super_class.clone()
    }

    pub fn set_interfaces(&mut self, interfaces: Vec<Arc<Class>>) {
        self.interfaces = interfaces;
    }

    pub fn get_interfaces(&self) -> &Vec<Arc<Class>> {
        &self.interfaces
    }

    pub fn get_interface_names(&self) -> &Vec<String> {
        &self.interface_names
    }

    pub fn get_instance_slot_count(&self) -> usize {
        self.instance_slot_count
    }

    pub fn set_instance_slot_count(&mut self, count: usize) {
        self.instance_slot_count = count;
    }

    pub fn get_static_slot_count(&self) -> usize {
        self.static_slot_count
    }

    pub fn set_static_slot_count(&mut self, count: usize) {
        self.static_slot_count = count;
    }

    pub fn get_name(&self) -> String {
        self.name.clone()
    }

    pub fn get_super_class_name(&self) -> String {
        self.super_class_name.clone()
    }

    pub fn get_j_class(&self) -> Option<*mut Object> {
        self.j_class.clone()
    }

    pub fn set_j_class(&mut self, j_class: Option<*mut Object>) {
        self.j_class = j_class;
    }

    pub fn get_source_file(&self) -> String {
        self.source_file.clone()
    }

    pub fn get_source_file_class_name(&self) -> Option<String> {
        if "Unknown" == &self.source_file || self.source_file.is_empty() {
            None
        } else {
            let package_name = self.get_package_name().to_string() + "/";
            let mut class_name = if self.source_file.ends_with(".java") {
                let len = self.source_file.len() - 5;
                &self.source_file[..len]
            } else {
                &self.source_file
            };
            if package_name.len() == 1 {
                Some(class_name.to_string())
            } else {
                Some(package_name + class_name)
            }
        }
    }

    pub fn get_access_flags(&self) -> u16 {
        self.access_flags
    }

    pub fn is_public(&self) -> bool {
        0 != self.access_flags & ACC_PUBLIC
    }

    pub fn is_final(&self) -> bool {
        0 != self.access_flags & ACC_FINAL
    }

    pub fn is_super(&self) -> bool {
        0 != self.access_flags & ACC_SUPER
    }

    pub fn is_interface(&self) -> bool {
        0 != self.access_flags & ACC_INTERFACE
    }

    pub fn is_abstract(&self) -> bool {
        0 != self.access_flags & ACC_ABSTRACT
    }

    pub fn is_synthetic(&self) -> bool {
        0 != self.access_flags & ACC_SYNTHETIC
    }

    pub fn is_annotation(&self) -> bool {
        0 != self.access_flags & ACC_ANNOTATION
    }

    pub fn is_enum(&self) -> bool {
        0 != self.access_flags & ACC_ENUM
    }

    // 类other想访问类self，需要满足两个条件之一：self是public，或者self和other在同一个运行时包内。
    pub fn is_accessible_to(&self, other: &Class) -> bool {
        self.is_public() || self.get_package_name() == other.get_package_name()
    }

    pub fn is_array(&self) -> bool {
        self.name.starts_with("[")
    }

    // 是否是基本类型
    pub fn is_primitive(&self) -> bool {
        let key = self.name.as_str();
        PRIMITIVE_TYPES.contains_key(key)
    }

    pub fn get_package_name(&self) -> &str {
        let last = self.name.rfind('/');
        match last {
            Some(i) => &self.name[..i],
            None => ""
        }
    }

    pub fn get_main_method(&self) -> Option<Arc<Method>> {
        self.get_method("main", "([Ljava/lang/String;)V", true)
    }

    pub fn get_clinit_method(&self) -> Option<Arc<Method>> {
        self.get_method("<clinit>", "()V", true)
    }

    pub fn get_thread_run_method(&self) -> Option<Arc<Method>> {
        self.get_method("run", "()V", false)
    }

    pub fn get_method(&self, name: &str, descriptor: &str, is_static: bool) -> Option<Arc<Method>>  {
        let mut c = Some(self.arc());
        while let Some(class) = c {
            for method in &class.methods {
                if method.is_static() == is_static
                && method.get_name() == name
                && method.get_descriptor() == descriptor {
                    return Some(method.clone());
                }
            }
            c = class.super_class.clone();

        }
        None
    }

    pub fn get_method_any(&self, name: &str, descriptor: &str) -> Option<Arc<Method>>  {
        let mut c = Some(self.arc());
        while let Some(class) = c {
            for method in &class.methods {
                if method.get_name() == name
                && method.get_descriptor() == descriptor {
                    return Some(method.clone());
                }
            }
            c = class.super_class.clone();

        }
        None
    }

    pub fn get_method_by_name(&self, name: &str) -> Option<Arc<Method>>  {
        let mut c = Some(self.arc());
        while let Some(class) = c {
            for method in &class.methods {
                if method.get_name() == name {
                    return Some(method.clone());
                }
            }
            c = class.super_class.clone();

        }
        None
    }

    pub fn fmt(&self) {
        println!("Class:{{ access_flags: {}, name: {}, super_class_name: {}, constant_pool: {}, fields: len {}, method: len {}, loader: {}, super_class: {}, interfaces: len {}, instance_slot_count: {}, static_slot_count: {}}}",
            self.access_flags,
            self.name,
            self.super_class_name,
            match &self.constant_pool {
                Some(cp) => format!("{}", cp),
                None => format!("None")
            },
            self.fields.len(),
            self.methods.len(),
            if self.loader.is_none() {"None"} else {"Some"},
            if self.super_class.is_none() {"None"} else {"Some"},
            self.interfaces.len(),
            self.instance_slot_count,
            self.static_slot_count,
        )
    }

    pub fn java_name(&self) -> String {
        self.name.clone().replace("/", ".")
    }

    pub fn get_instance_method(&self, name: &str, descriptor: &str) -> Option<Arc<Method>> {
        self.get_method(name, descriptor, false)
    }

    pub fn get_static_method(&self, name: &str, descriptor: &str) -> Option<Arc<Method>> {
        self.get_method(name, descriptor, true)
    }

    // reflection
    pub fn set_ref_var(&self, name: &str, descriptor: &str, _ref: *mut Object) {
        let field: Option<Arc<Field>> = Class::get_field(Some(self.arc()), name, descriptor, true);

        self.static_vars.write().unwrap().set_ref(field.unwrap().get_slot_id(), Some(_ref));
    }

    pub fn get_ref_var(&mut self, name: &str, descriptor: &str) -> Option<*mut Object> {
        let field = Class::get_field(Some(self.arc()), name, descriptor, true);

        self.static_vars.read().unwrap().get_ref(field.unwrap().get_slot_id())
    }

    pub fn get_constructor(&self, descriptor: &str) -> Option<Arc<Method>> {
        self.get_instance_method("<init>", descriptor)
    }

    pub fn get_constructors(&self, public_only: bool) -> Vec<Arc<Method>> {
        self.methods.clone().into_iter().filter(|method|
            method.is_constructor() && (!public_only || method.is_public())
        ).collect()
    }

    pub fn arc(&self) -> Arc<Class> {
        match &self.this {
            Some(this) => this.clone(),
            None => panic!("Class未设置this引用(Arc<Class>)")
        }
    }

    pub fn original_class(&self) -> Option<Arc<Class>> {
        self.original_class.clone()
    }

    pub fn get_bootstrap_method(&self, index: usize) -> Option<BootstrapMethod> {
        match &self.bootstrap_methods {
            Some(attribute) => Some(attribute.get_bootstrap_method(index)),
            None => None
        }
    }

    pub fn get_enclosing_method(&self) -> Option<EnclosingMethodAttribute> {
        self.enclosing_method.clone()
    }

    pub fn get_declared_methods(&self) -> Vec<Arc<Method>> {
        self.methods.clone().into_iter().filter(|m| m.get_name() != "<init>" && m.get_name() != "<clinit>").collect()
    }
}

// class_hierarchy
impl Class {
    // 后续参考： java虚拟机规范 8.6.5
    pub fn is_assignable_from(&self, other: &Class) -> bool {
        let s = other;
        let t =  self;
        if std::ptr::eq(s, t) {
            return true;
        }
        if !s.is_array() {
            if !s.is_interface() {
                // s is class
                if !t.is_interface() {
                    // t is not interface
                    return s.is_sub_class_of(t);
                } else {
                    // t is interface
                    return s.is_implements(t);
                }
            } else {
                // s is interface
                if !t.is_interface() {
                    return t.is_jl_object();
                } else {
                    return t.is_super_interface_of(s);
                }
            }
        } else {
            // s is array
            if !t.is_array() {
                if !t.is_interface() {
                    // t is class
                    return t.is_jl_object();
                } else {
                    // t is interface
                    return t.is_jl_cloneable() || t.is_jio_serializable();
                }
            } else {
                // t.is array
                let sc = s.component_class();
                let tc = t.component_class();
                return Arc::ptr_eq(&sc, &tc) || tc.is_assignable_from(sc.as_ref());
            }
        }
        false
    }

    // 判断是否为其子类
    pub fn is_sub_class_of(&self, other: &Class) -> bool {
        let mut sc = self.super_class.clone();
        while let Some(c) = sc {
            if std::ptr::eq(c.as_ref(), other) {
                return true;
            }
            sc = c.super_class.clone();
        }
        false
    }

    // 判断是否实现了改接口（自身及直接或间接父类）
    pub fn is_implements(&self, iface: &Class) -> bool {
        for i in &self.interfaces {
            let i = &**i;
            if std::ptr::eq(i, iface) || i.is_sub_interface_of(iface) {
                return true;
            }
        }
        let mut sc = self.super_class.clone();
        while let Some(c) = sc {
            let cr = &*c  ;
            for i in cr.get_interfaces() {
                let ir = &**i ;
                if std::ptr::eq(ir, iface) || ir.is_sub_interface_of(iface) {
                    return true;
                }
            }
            sc = cr.super_class.clone();
        }
        false
    }

    // 判断是否为其子接口
    pub fn is_sub_interface_of(&self, iface: &Class) -> bool {
        for super_interface in &self.interfaces {
            let super_iface = unsafe { &**super_interface };
            if std::ptr::eq(super_iface, iface) || super_iface.is_sub_interface_of(iface) {
                return true;
            }
        }
        false
    }

    // 判断是否为其父接口
    pub fn is_super_interface_of(&self, other: &Class) -> bool {
        other.is_sub_interface_of(self)
    }

    fn is_jl_object(&self) -> bool {
        self.name == "java/lang/Object"
    }

    fn is_jl_cloneable(&self) -> bool {
        self.name == "java/lang/Cloneable"
    }

    fn is_jio_serializable(&self) -> bool {
        self.name == "java/lang/Serializable"
    }

}
